package cn.kevinkun.LeanCloud;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.json.JSONException;
import org.json.JSONObject;

import com.google.appinventor.components.annotations.DesignerComponent;
import com.google.appinventor.components.annotations.SimpleEvent;
import com.google.appinventor.components.annotations.SimpleFunction;
import com.google.appinventor.components.annotations.SimpleObject;
import com.google.appinventor.components.annotations.UsesPermissions;
import com.google.appinventor.components.common.ComponentCategory;
import com.google.appinventor.components.runtime.AndroidNonvisibleComponent;
import com.google.appinventor.components.runtime.Component;
import com.google.appinventor.components.runtime.ComponentContainer;
import com.google.appinventor.components.runtime.EventDispatcher;
import com.google.appinventor.components.runtime.ReplForm;

import android.content.Context;
import android.content.res.AssetManager;
import android.os.Build;

@DesignerComponent(version = 20241014, category = ComponentCategory.EXTENSION, description = "http://www.kevinkun.cn/leancloud.html", iconName = "aiwebres/leancloud.svg", nonVisible = true)
@SimpleObject(external = true)
@UsesPermissions(permissionNames = "android.permission.INTERNET")
public class LeanFile extends AndroidNonvisibleComponent implements Component {

	String url = "";
	String appid = "";
	String appkey = "";
	String apiversion = "1.1";
	Map<String, String> headers = new HashMap<String, String>();
	private final Context context;

	public LeanFile(ComponentContainer container) {
		super(container.$form());
		context = container.$context();
	}

	@SimpleFunction(description = "")
	public void Init(String restApiUrl, String appId, String appKey) {
		url = restApiUrl;
		appid = appId;
		appkey = appKey;

	}

	@SimpleFunction(description = "")
	public void Upload(String filepath, String filetype) {

		Date dNow = new Date();
		SimpleDateFormat ft = new SimpleDateFormat("yyyyMMdd_hhmmss");
		String ext = extName(filepath);
		String realUrl = url + "/" + apiversion + "/files/" + ft.format(dNow);
		if (!ext.equals("")) {
			realUrl = realUrl + "." + ext;
		}

		headers.clear();
		headers.put("X-LC-Id", appid);
		headers.put("X-LC-Key", appkey);
		headers.put("Content-Type", filetype);

		byte[] body = null;
		try {
			body = inputStream2ByteArray(openFile(filepath));
		} catch (IOException e1) {

		}

		HttpUtils.doHttpReqeust("POST", realUrl, headers, body, new HttpUtils.Callback() {

			@Override
			public void onSuccess(String result) {
				form.runOnUiThread(new Runnable() {
					@Override
					public void run() {
						JSONObject object;
						try {
							object = new JSONObject(result);
							if (object.has("error")) {
								OnError(object.getString("error"));
							} else {
								String url = object.getString("url");
								// String size = object.getString("size");
								Uploaded(url);
							}
						} catch (JSONException e) {
							OnError(e.getMessage());
						}

					}
				});
			}

			@Override
			public void onError(String error) {
				form.runOnUiThread(new Runnable() {
					@Override
					public void run() {
						OnError(error);
					}
				});
			}
		});

	}

	public static String extName(String filename) {
		int index = filename.lastIndexOf(".");

		if (index == -1) {
			return "";
		}
		String result = filename.substring(index + 1);
		return result;

	}

	public InputStream openFile(String filename) throws IOException {
		if (filename.startsWith("file://")) {
			filename = filename.substring(7);
		}
		InputStream inputStream = null;
		if (filename.startsWith("//")) {
			filename = filename.substring(2);
			if (ReplForm.class.isInstance(form)) {
				if (Build.VERSION.SDK_INT >= 29) {
					String realpath = this.context.getExternalFilesDir(null).getPath() + "/assets/" + filename;
					inputStream = new FileInputStream(realpath);
				} else {
					String realpath = this.context.getExternalFilesDir(null).getPath() + "/AppInventor/assets/"
							+ filename;
					inputStream = new FileInputStream(realpath);
				}

			} else {
				final AssetManager am = form.getAssets();
				inputStream = am.open(filename);
			}
		} else if (filename.startsWith("~/")) {
			filename = filename.substring(1);
			String privateFolder = context.getFilesDir().getPath();
			inputStream = new FileInputStream(privateFolder + filename);

		} else if (!filename.contains("/")) {
			String path = this.context.getExternalFilesDir(null).getPath() + "/" + filename;
			inputStream = new FileInputStream(path);
		} else {
			inputStream = new FileInputStream(filename);
		}
		return inputStream;
	}

	private byte[] inputStream2ByteArray(InputStream in) throws IOException {

		ByteArrayOutputStream out = new ByteArrayOutputStream();
		byte[] buffer = new byte[1024 * 4];
		int n = 0;
		while ((n = in.read(buffer)) != -1) {
			out.write(buffer, 0, n);
		}
		return out.toByteArray();
	}

	@SimpleEvent
	public void OnError(String error) {
		EventDispatcher.dispatchEvent(this, "OnError", error);
	}

	@SimpleEvent
	public void Uploaded(String url) {
		EventDispatcher.dispatchEvent(this, "Uploaded", url);
	}

}
